package vn.vfriends.soffice.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import org.omnifaces.util.Faces;
import org.primefaces.context.RequestContext;
import org.primefaces.model.CheckboxTreeNode;
import org.primefaces.model.TreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vn.vfriends.soffice.entity.Group;
import vn.vfriends.soffice.entity.Menu;
import vn.vfriends.soffice.entity.Permission;
import vn.vfriends.soffice.service.GroupService;
import vn.vfriends.soffice.service.MenuService;
import vn.vfriends.soffice.service.PermissionService;

/**
 *
 * @author chaungoctuan@gmail.com
 */
@ManagedBean
@ViewScoped
public class GroupBean implements Serializable {

    private static final Logger logger = LoggerFactory.getLogger(GroupBean.class);
    
    @Inject private GroupService groupService;
    
    @Inject private MenuService menuService;
    
    @Inject private PermissionService permissionService;
    
    private Group[] selectedGroups;
    
    private Group group;
    
    private Integer groupId;
    
    private TreeNode root;

    private TreeNode[] selectedNodes;
    
    public TreeNode getRoot() {
        return root;
    }

    public void setRoot(TreeNode root) {
        this.root = root;
    }

    public TreeNode[] getSelectedNodes() {
        return selectedNodes;
    }

    public void setSelectedNodes(TreeNode[] selectedNodes) {
        this.selectedNodes = selectedNodes;
    }

    public Integer getGroupId() {
        return groupId;
    }

    public void setGroupId(Integer groupId) {
        this.groupId = groupId;
    }

    public Group[] getSelectedGroups() {
        return selectedGroups;
    }

    public void setSelectedGroups(Group[] selectedGroups) {
        this.selectedGroups = selectedGroups;
    }

    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }
    
    public List<Group> getGroupList() {
        return this.groupService.findAll();
    }
    
    public Group getGroup(String name) {
        return this.groupService.findByName(name);
    }
    
    public void preEditAction() {
        try {
            if(this.group != null){
                Map<String,List<String>> params = new HashMap<String, List<String>>();
                params.put("groupId", Arrays.asList(this.group.getId().toString()));
                RequestContext.getCurrentInstance().openDialog("edit", null, params);
            } else if (this.selectedGroups == null || this.selectedGroups.length == 0) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Thông báo", "Hãy chọn một nhóm");
                RequestContext.getCurrentInstance().showMessageInDialog(message);
            } else if (this.selectedGroups.length > 1) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Thông báo", "Chỉ chọn một nhóm");
                RequestContext.getCurrentInstance().showMessageInDialog(message);
            } else {
                this.group = this.selectedGroups[0];
                Map<String,List<String>> params = new HashMap<String, List<String>>();
                params.put("groupId", Arrays.asList(this.group.getId().toString()));
                RequestContext.getCurrentInstance().openDialog("edit", null, params);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    public void preRenderEditView() {
        this.group = new Group();
        this.group = this.groupService.find(groupId);
        if(this.group == null) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Nhóm người dùng không tồn tại");
            Faces.getContext().addMessage(null, message);
        }
    }
    
    public void updateAction() {
        try {
            this.groupService.edit(this.group);
            this.reset();
            RequestContext.getCurrentInstance().closeDialog("editDialog");
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    public void preNewAction() {
        RequestContext.getCurrentInstance().openDialog("new");
    }
    
    public void preRenderNewView() {
        this.group = new Group();
    }
    
    public void saveAction() {
        try {
            this.groupService.create(this.group);
            this.reset();
            RequestContext.getCurrentInstance().closeDialog("newDialog");
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    public void preDeleteAction() {
        try {
            if ((this.group == null) && (this.selectedGroups == null || this.selectedGroups.length == 0)) {
                RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Thông báo", "Hãy chọn một hoặc nhiều nhóm");
                RequestContext.getCurrentInstance().showMessageInDialog(message);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    public void deleteAction() {
        try {
            if(this.group != null) {
                this.groupService.remove(group);
            }
            else {
                for(Group selectedGroup : selectedGroups) {
                    this.groupService.remove(selectedGroup);
                }
            }
            this.reset();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    public void preGrantAction() {
        try {
            if(this.group != null){
                Map<String,List<String>> params = new HashMap<String, List<String>>();
                params.put("groupId", Arrays.asList(this.group.getId().toString()));
                
                Map<String,Object> options = new HashMap<String, Object>();
                options.put("contentHeight", 500);
                
                RequestContext.getCurrentInstance().openDialog("grant", options, params);
            } else if (this.selectedGroups == null || this.selectedGroups.length == 0) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Thông báo", "Hãy chọn một nhóm");
                RequestContext.getCurrentInstance().showMessageInDialog(message);
            } else if (this.selectedGroups.length > 1) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Thông báo", "Chỉ chọn một nhóm");
                RequestContext.getCurrentInstance().showMessageInDialog(message);
            } else {
                this.group = this.selectedGroups[0];
                Map<String,List<String>> params = new HashMap<String, List<String>>();
                params.put("groupId", Arrays.asList(this.group.getId().toString()));
                
                Map<String,Object> options = new HashMap<String, Object>();
                options.put("contentHeight", 500);
                
                RequestContext.getCurrentInstance().openDialog("grant", options, params);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    public void preRenderGrantView() {
        this.group = new Group();
        this.group = this.groupService.find(groupId);
        if(this.group == null) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Nhóm người dùng không tồn tại");
            Faces.getContext().addMessage(null, message);
        } else {
            this.initNode();
        }
    }
    
    public void grantAction() {
        try {
            if(selectedNodes != null && selectedNodes.length > 0) {
                List<Menu> grantedMenus = new ArrayList<Menu>();
                List<Permission> grantedPermissions = new ArrayList<Permission>();
                for(TreeNode node : selectedNodes) {
                    Object data = node.getData();
                    if(data instanceof Menu) {
                        grantedMenus.add((Menu)data);
                    } else if(data instanceof Permission) {
                        grantedPermissions.add((Permission)data);
                    }
                }
                this.group.setMenus(grantedMenus);
                this.group.setPermissions(grantedPermissions);
            }
            
            this.groupService.edit(this.group);
            this.reset();
            RequestContext.getCurrentInstance().closeDialog("grantDialog");
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Thông báo", "Lỗi hệ thống");
            RequestContext.getCurrentInstance().showMessageInDialog(message);
        }
    }
    
    private void reset() {
        this.group = null;
        this.groupId = 0;
        this.selectedGroups = null;
        this.root = null;
        this.selectedNodes = null;
    }
    
    private void initNode() {
        root = new CheckboxTreeNode("Menu/quyền", null);
        List<Menu> menus = this.menuService.findFirstLevel();
        for(Menu menu : menus) {
            this.initNode(menu, root);
        }
    }
    
    private void initNode(Menu parentMenu, TreeNode parentNode) {
        TreeNode node = new CheckboxTreeNode(parentMenu, parentNode);
        
        if(this.group.getMenus().contains(parentMenu)) {
            node.setSelected(true);
        }
        
        List<Menu> children = this.menuService.findChildren(parentMenu);
        if (children.size() > 0) {
            for(Menu child : children) {
                this.initNode(child, node);
            }
        }
        
        List<Permission> permissions = this.permissionService.findPermissionsByMenu(parentMenu);
        if(permissions.size() > 0) {
            for(Permission permission : permissions) {
                TreeNode childNode = new CheckboxTreeNode(permission, node);
                if(this.group.getPermissions().contains(permission)) {
                    childNode.setSelected(true);
                }
            }
        }
    }
}
